/**
 *
 *   格式       描述
 *   --------   ---------------------------------------------------------------
 *   yy         年份后两位，如2015取后两位是15。
 *   yyyy       年份四位。
 *   M          月份，取值1 ~ 12。
 *   MM         月份，取值01 ~ 12，如果月份为个位数，前面补0。
 *   MMM        月份缩写，如一月的英文缩写为Jan，中文缩写为一。
 *   MMMM       月份全称，如January、一月。
 *   d          日期在月中的第几天，取值1~31。
 *   dd         日期在月中的第几天，取值01~31，如果天数为个位数，前面补0。
 *   ddd        星期缩写，取值日、一、二、三、四、五、六。
 *   dddd       星期全称，取值星期日、星期一、星期二、星期三、星期四、星期五、星期六。
 *   H          24小时进制，取值0~23。
 *   HH         24小时进制，取值00~23，如果小时为个位数，前面补0。
 *   h          12小时进制，取值0~11。
 *   hh         12小时进制，取值00~11，如果小时为个位数，前面补0。
 *   m          分钟，取值0~59。
 *   mm         分钟，取值00~59，如果为个位数，前面补0。
 *   s          秒，取值0~59。
 *   ss         秒，取值00~59，如果为个位数，前面补0。
 *   S          毫秒，取值0~999。
 *   SS         毫秒，取值00~999，如果不足两位数，前面补0。
 *   SSS        毫秒，取值000~999，如果不足三位数，前面补0。
 *   t          上午、下午缩写。
 *   tt         上午、下午全称。
 *   --------   ---------------------------------------------------------------
 *
 * @author accountwcx@qq.com
 * @date   2015-08-12
 */
DateUtils = (function(){
    /*
    var locale = {
        dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
        shortDayNames: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
        monthNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
        shortMonthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
        am: 'AM',
        pm: 'PM',
        shortAm: 'A',
        shortPm: 'P'
    };
//    	YEAR : 1,
//    	MONTH : 2,
//	    DATE : 5,
//	    HOUR : 10,
//	    MINUTE : 12,
//	    SECOND : 13,
//	    MILLISECOND : 14,
    */

    var __locale = {
        dayNames: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
        shortDayNames: ["日", "一", "二", "三", "四", "五", "六"],
        monthNames: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
        shortMonthNames: ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"],
        am: "上午",
        pm: "下午",
        shortAm: '上',
        shortPm: '下'
    };
    var __dayTime = 1000*60*60*24;
    var __hourTime = 1000*60*60;
    var __minuteTime = 1000*60;
    var __secondTime = 1000;


    /**
     * 左边补0
     */
    function leftPad(str, size){
        var result = '' + str;

        while (result.length < size) {
            result = '0' + result;
        }

        return result;
    }

    var parseToken = (function(){
        var match2 = /\d{2}/,          // 00 - 99
            //match3 = /\d{3}/,          // 000 - 999
            match4 = /\d{4}/,          // 0000 - 9999
            match1to2 = /\d{1,2}/,     // 0 - 99
            match1to3 = /\d{1,3}/,     // 0 - 999
            //match1to4 = /\d{1,4}/,     // 0 - 9999
            match2w = /.{2}/,         // 匹配两个字符
            match1wto2w = /.{1,2}/,   // 匹配1~2个字符
            map = {
                //年的后两位
                'yy': {
                    regex: match2,
                    name: 'year'
                },
                //年
                'yyyy': {
                    regex: match4,
                    name: 'year'
                },
                //两位数的月，不到两位数则补0
                'MM': {
                    regex: match2,
                    name: 'month'
                },
                //月
                'M': {
                    regex: match1to2,
                    name: 'month'
                },
                //两位数的日期，不到两位数则补0
                'dd': {
                    regex: match2,
                    name: 'date'
                },
                //日期
                'd': {
                    regex: match1to2,
                    name: 'date'
                },
                //两位数的小时，24小时进制
                'HH': {
                    regex: match2,
                    name: 'hours'
                },
                //小时，24小时进制
                'H': {
                    regex: match1to2,
                    name: 'hours'
                },
                //两位数的小时，12小时进制
                'hh': {
                    regex: match2,
                    name: 'hours'
                },
                //小时，12小时进制
                'h': {
                    regex: match1to2,
                    name: 'hours'
                },
                //两位数的分钟
                'mm': {
                    regex: match2,
                    name: 'minutes'
                },
                //分钟
                'm': {
                    regex: match1to2,
                    name: 'minutes'
                },
                's': {
                    regex: match1to2,
                    name: 'seconds'
                },
                'ss': {
                    regex: match2,
                    name: 'seconds'
                },
                //上午、下午
                'tt': {
                    regex: match2w,
                    name: 't'
                },
                //上午、下午
                't': {
                    regex: match1wto2w,
                    name: 't'
                },
                //毫秒
                'S': {
                    regex: match1to3,
                    name: 'millisecond'
                },
                //毫秒
                'SS': {
                    regex: match1to3,
                    name: 'millisecond'
                },
                //毫秒
                'SSS': {
                    regex: match1to3,
                    name: 'millisecond'
                }
            };

        return function(token, str, dateObj){
            var result, part = map[token];
            if(part){
                result = str.match(part.regex);
                if(result){
                    dateObj[part.name] = result[0];
                    return result[0];
                }
            }

            return null;
        };
    })();

    return {
        locale: __locale,
        formatDate: function(val, pattern){
            if(Object.prototype.toString.call(val) !== '[object Date]'){
                return '';
            }

            if(Object.prototype.toString.call(pattern) !== '[object String]' || pattern === ''){
                pattern = 'yyyy-MM-dd HH:mm:ss';
            }

            var fullYear = val.getFullYear(),
                month = val.getMonth(),
                day = val.getDay(),
                date = val.getDate(),
                hours = val.getHours(),
                minutes = val.getMinutes(),
                seconds = val.getSeconds(),
                milliseconds = val.getMilliseconds();

            return pattern.replace(/(\\)?(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|SS?S?)/g, function (m) {
                if (m.charAt(0) === '\\') {
                    return m.replace('\\', '');
                }

                var locale = DateUtils.locale;

                switch (m) {
                    case "hh":
                        return leftPad(hours < 13 ? (hours === 0 ? 12 : hours) : (hours - 12), 2);
                    case "h":
                        return hours < 13 ? (hours === 0 ? 12 : hours) : (hours - 12);
                    case "HH":
                        return leftPad(hours, 2);
                    case "H":
                        return hours;
                    case "mm":
                        return leftPad(minutes, 2);
                    case "m":
                        return minutes;
                    case "ss":
                        return leftPad(seconds, 2);
                    case "s":
                        return seconds;
                    case "yyyy":
                        return fullYear;
                    case "yy":
                        return (fullYear + '').substring(2);
                    case "dddd":
                        return locale.dayNames[day];
                    case "ddd":
                        return locale.shortDayNames[day];
                    case "dd":
                        return leftPad(date, 2);
                    case "d":
                        return date;
                    case "MMMM":
                        return locale.monthNames[month];
                    case "MMM":
                        return locale.shortMonthNames[month];
                    case "MM":
                        return leftPad(month + 1, 2);
                    case "M":
                        return month + 1;
                    case "t":
                        return hours < 12 ? locale.shortAm : locale.shortPm;
                    case "tt":
                        return hours < 12 ? locale.am : locale.pm;
                    case "S":
                        return milliseconds;
                    case "SS":
                        return leftPad(milliseconds, 2);
                    case "SSS":
                        return leftPad(milliseconds, 3);
                    default: 
                        return m;
                }
            });
        },

        parseDate: function(val, pattern){
            if(!val){
                return null;
            }

            if(Object.prototype.toString.call(val) === '[object Date]'){
                // 如果val是日期，则返回。
                return val;
            }

            if(Object.prototype.toString.call(val) !== '[object String]'){
                // 如果val不是字符串，则退出。
                return null;
            }

            var time;
            if(Object.prototype.toString.call(pattern) !== '[object String]' || pattern === ''){
                // 如果fmt不是字符串或者是空字符串。
                // 使用浏览器内置的日期解析
                time = Date.parse(val);
                if(isNaN(time)){
                    return null;
                }

                return new Date(time);
            }

            var i, token, tmpVal, 
                tokens = pattern.match(/(\\)?(dd?|MM?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|SS?S?|.)/g),
                dateObj = {
                    year: 0,
                    month: 1,
                    date: 0,
                    hours: 0,
                    minutes: 0,
                    seconds: 0,
                    millisecond: 0
                };

            for(i = 0; i < tokens.length; i++){
                token = tokens[i];
                tmpVal = parseToken(token, val, dateObj);

                if(tmpVal !== null){
                    if(val.length > tmpVal.length){
                        val = val.substring(tmpVal.length);
                    }else{
                        val = '';
                    }
                }else{
                    val = val.substring(token.length);
                }
            }

            if(dateObj.t){
                if(DateUtils.locale.pm === dateObj.t || DateUtils.locale.shortPm === dateObj.t){
                    dateObj.hours = (+dateObj.hours) + 12;
                }
            }

            dateObj.month -= 1;

            return new Date(dateObj.year, dateObj.month, dateObj.date, dateObj.hours, dateObj.minutes, dateObj.seconds, dateObj.millisecond);
        },
        isSameDay : function( date1, date2){
        	var time1 = Date.parse(date1);
        	var time2 = Date.parse(date2);
        	if(Math.abs(time1-time2)<__dayTime){
        		return true;
        	}else{
        		return false;
        	}
        	
        },
	    addSeconds:function(date,amount){
            if(!(date instanceof Date)){
                return null;
            }
            if(isNaN(amount)){
                return date;
            }
            var newTime = Date.parse(date)+amount*__secondTime;
            var newValue = new Date(newTime);
            return newValue;
	    },
	    addMinutes:function(date,amount){
            if(!(date instanceof Date)){
                return null;
            }
            if(isNaN(amount)){
                return date;
            }
            var newTime = Date.parse(date)+amount*__minuteTime;
            var newValue = new Date(newTime);
            return newValue;
	    },
	    addHours:function(date,amount){
            if(!(date instanceof Date)){
                return null;
            }
            if(isNaN(amount)){
                return date;
            }
            var newTime = Date.parse(date)+amount*__hourTime;
            var newValue = new Date(newTime);
            return newValue;
	    },
	    _addMonths:function(date,amount){
	    },
	    _addYears:function(date,amount){
	    },
        /**
         * 返回毫秒
         * 扩展方法
         */
        getTime: function(date){
        	return Date.parse(date);
        }
//TODO        ,
//        truncate (java.util.Date date, int field)
        
    };
})();

/**
 * 常用的字符串处理方法
 * @author accountwcx@qq.com
 * @date 2015-08-12
 */
StringUtils = (function() {

	// 不用这个了   字符串去掉两边空白正则表达式
	//        trimRegex = /^[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+|[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+$/g,

	// 字符串格式化正则表达式
	var formatRegex = /\{(\d+)\}/g;

	var htmlEncodeMap = {
		'"' : "&quot;",
		'&' : "&amp;",
		"'" : "&#39;",
		'<' : "&lt;",
		'>' : "&gt;"
	};

	var htmlDecodeMap = {
		'&#39;' : "'",
		'&amp;' : "&",
		'&gt;' : ">",
		'&lt;' : "<",
		'&quot;' : '"'
	};

	var htmlEncodeRegex = /(&|>|<|"|')/g;

	var htmlDecodeRegex = /(&amp;|&gt;|&lt;|&quot;|&#39;|&#[0-9]{1,5};)/g;

	return {
		/**
		 * 除去字符串两端的空白字符
		 */
		trim : function(str) {
			// return str.replace(trimRegex, '');
			return str.replace(/(^\s*)|(\s*$)/g, "");
		},
		/**
		 * 删除左边的空格
		 */
		ltrim : function(str) {
			return str.replace(/(^\s*)/g, "");
		},
		/**
		 * 删除右边的空格
		 */
		rtrim : function(str) {
			return str.replace(/(\s*$)/g, "");
		},

		/**
		 * 允许用格式化的方式给传值 var cls = 'css-class', text = '内容'; var str =
		 * Rhui.String.format('<div class="{0}">{1}</div>', cls, text); //
		 * str的内容是 <div class="css-class">内容</div>
		 * @param str
		 *            {String} 待格式化的字符串
		 * @param params...
		 *            {Object} 与字符串中{0}、{1}...匹配的内容
		 * @return 返回格式化后的字符串
		 */
		format : function(str) {
			var i, args = arguments, len = args.length, arr = [];
			for (i = 1; i < len; i++) {
				arr.push(args[i]);
			}

			return str.replace(formatRegex, function(m, i) {
				return arr[i];
			});
		},

		/**
		 * 填补字符串左边
		 * @param str
		 *            {String} 原字符串
		 * @param size
		 *            {Number} 填补后的长度
		 * @param character
		 *            {String} 填补的字符，如果不填则为空字符' '
		 * @return 返回填补后的字符串
		 */
		leftPad : function(str, size, character) {
			var result = '' + str;

			if (Object.prototype.toString.call(character) !== '[object String]') {
				character = ' ';
			}

			while (result.length < size) {
				result = character + result;
			}

			return result;
		},

		/**
		 * 填补字符串右边
		 * @param str
		 *            {String} 原字符串
		 * @param size
		 *            {Number} 填补后的长度
		 * @param character
		 *            {String} 填补的字符，如果不填则为空字符' '
		 * @return 返回填补后的字符串
		 */
		rightPad : function(str, size, character) {
			var result = '' + str;

			if (Object.prototype.toString.call(character) !== '[object String]') {
				character = ' ';
			}

			while (result.length < size) {
				result += character;
			}

			return result;
		},

		/**
		 * 把字符串中的html字符转义
		 * @param str
		 *            {String}
		 * @return 返回转义后的字符
		 */
		htmlEncode : function(str) {
			if (Object.prototype.toString.call(str) === '[object String]') {
				return str.replace(htmlEncodeRegex, function(match, val) {
					return htmlEncodeMap[val];
				});
			} else {
				return str;
			}
		},

		/**
		 * 把字符串中的html字符解码
		 * @param str
		 *            {String}
		 * @return 返回解码后的字符串
		 */
		htmlDecode : function(str) {
			if (Object.prototype.toString.call(str) === '[object String]') {
				return str.replace(htmlDecodeRegex, function(match, val) {
					return htmlDecodeMap[val];
				});
			} else {
				return str;
			}
		},
		/**
		 * 判断是否为空
		 */
		isEmpty : function(str) {
			if (str == undefined || str == null || str == "") {
				return true;
			} else {
				return false;
			}
		},
		/**
		 * 判断是否为空串
		 */
		isBlank : function(str) {
			if (str == undefined || str == null || str == "") {
				return true;
			} else {
				for ( var i in str) {
					if (str.charAt(i) != " ") {
						return false;
					}
				}
				return true;
			}
		},
		/**
		 * 判断是否为空
		 */
		isNotEmpty : function(str) {
			return !this.isEmpty(str);
		},
		/**
		 * 判断是否为空串
		 */
		isNotBlank : function(str) {
			return !this.isBlank(str);
		},
		/**
		 * 截取最大长度
		 */
		abbreviate:function(str,maxlen){
			if(str.length <= maxlen){
				return str;
			}else{
				return str.substr(0,maxlen)+"...";
			}
		},
		/**
		 *扩展函数
		 * 
		 */
		join:function(arr,splitStr,quoteStr){
			if(quoteStr==null){
				return arr.join(splitStr);
			}else{
				var newArr = [];
				for(var i in arr){
					newArr.push(quoteStr+arr[i]+quoteStr);
				}
				return newArr.join(splitStr);
			}
		}
	};
})();

/**
 * 常用的随机数处理方法
 */
RandomUtils = (function() {
	return {
		nextInt:function(begin,end){
			if(begin==null){
				begin = 0;
				end = 2147483647;
			}else if(end==null){
				end = 2147483647;
			}
			var randNum = Math.random();
			var detNum = (end-begin)*randNum;
			return begin + parseInt(detNum);
		},
		nextLong:function(begin,end){
			if(begin==null){
				begin = 0;
				end = Number.MAX_SAFE_INTEGER;
			}else if(end==null){
				end = Number.MAX_SAFE_INTEGER;
			}
			var randNum = Math.random();
			var detNum = (end-begin)*randNum;
			return begin + parseLong(detNum);
		},
		nextDouble:function(begin,end){
			if(begin==null){
				begin = 0;
				end = Number.MAX_VALUE;
			}else if(end==null){
				end = Number.MAX_VALUE;
			}
			var randNum = Math.random();
			var detNum = (end-begin)*randNum;
			return begin + detNum;
		}
	}
})();